package com.nova.scenic.projectlibs.util.adapter;

import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;

import com.nova.scenic.projectlibs.R;
import com.nova.scenic.projectlibs.util.debug.MyLog;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class SimpleAdapter<T> extends BaseAdapter implements Filterable {
	private static final String TAG = SimpleAdapter.class.getSimpleName();
	private boolean DEBUG = true;
	List<T> mObjects = null;
	private Context mContext;
	private List<T> mOriginalValues;
	private Object mLock = new Object();
	private ArrayFilter mFilter;

    public static List<Integer> getDebugListData(int n){
        List<Integer> list = new ArrayList<Integer>();
        for(int i = 0;i < n; i++){
            list.add( i);
        }

        return list;
    }

	public SimpleAdapter(Context context, List<T> list) {
		mContext = context;
		this.mObjects = list;
	}

	public Context getContext(){
		return mContext;
	}

	@Override
	public int getCount() {
		if (mObjects == null) {
			return 0;
		}
		return mObjects.size();
	}

	@Override
	public T getItem(int position) {
		if (mObjects == null) {
			return null;
		}
		return mObjects.get(position);
	}



	@Override
	public long getItemId(int position) {
		return position;
	}

    @Override
	@SuppressLint("InflateParams")
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHold viewHold;
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.simple_list_item_two_text, null);
            viewHold = new ViewHold();
            viewHold.mIcon = (ImageView) convertView.findViewById(R.id.id_imgview_scenic_util_1);
            viewHold.text1 = (TextView) convertView.findViewById(R.id.id_txview_scenic_util_1);
            viewHold.text2 = (TextView) convertView.findViewById(R.id.id_txview_scenic_util_2);
            convertView.setTag(viewHold);
        } else {
            viewHold = (ViewHold) convertView.getTag();
        }

        T data = mObjects.get(position);

        initView(viewHold.mIcon, viewHold.text1, viewHold.text2, data);

        return convertView;
    }

    @Override
    public Filter getFilter() {
        if(DEBUG) MyLog.d(TAG, "getFilter");

        if (mFilter == null) {
            mFilter = new ArrayFilter();
        }
        return mFilter;
    }

	public void notifyDataSetChanged(List<T> data) {

		MyLog.i(TAG,"notifyDataSetChanged");
		if (mOriginalValues != null) {
			// 过滤模式
			mOriginalValues.clear();
			mOriginalValues.addAll(data);
		} else {
			if (this.mObjects == null) {
				this.mObjects = data;
			} else if(mObjects == data){

			}else{
				this.mObjects.clear();
				this.mObjects.addAll(data);
			}
		}

		notifyDataSetChanged();
	}

    public void add(List<T> data){
        mObjects.addAll(data);
        notifyDataSetChanged();
    }

    public void add(int location,List<T> data){
        mObjects.addAll(location,data);
        notifyDataSetChanged();
    }

    public void delete(List<T> data){
        mObjects.addAll(data);
        notifyDataSetChanged();
    }

	protected void initView(ImageView iv, TextView tx1, TextView tx2, T t) {
		tx1.setText(t.toString());
	}

    public List<T> copyData() {
        return new ArrayList<T>(mObjects) ;
    }

    public List<T> getData() {
        return mObjects ;
    }

    private static class ViewHold {

		public ImageView mIcon;
		public TextView text1;
		public TextView text2;
	}

	/**
	 * <p>
	 * An array filter constrains the content of the array adapter with a
	 * prefix. Each item that does not start with the supplied prefix is removed
	 * from the list.
	 * </p>
	 */
	private class ArrayFilter extends Filter {

		@Override
		protected FilterResults performFiltering(CharSequence prefix) {
			if(DEBUG) MyLog.d(TAG, "performFiltering " + prefix);
			FilterResults results = new FilterResults();

			if (mOriginalValues == null) {
				synchronized (mLock) {
					mOriginalValues = new ArrayList<>(mObjects);
				}
			}

			if (prefix == null || prefix.length() == 0) {
				ArrayList<T> list;
				synchronized (mLock) {
					list = new ArrayList<T>(mOriginalValues);
				}
				results.values = list;
				results.count = list.size();
			} else {
				String prefixString = prefix.toString().toLowerCase(Locale.getDefault());
				ArrayList<T> values;
				synchronized (mLock) {
					values = new ArrayList<>(mOriginalValues);
				}
				if(DEBUG) MyLog.d(TAG, "performFiltering all values " + values);
				final int count = values.size();
				final ArrayList<T> newValues = new ArrayList<T>();

				for (int i = 0; i < count; i++) {
					final T value = values.get(i);
					final String valueText = value.toString().toLowerCase(Locale.getDefault());
					if(DEBUG) MyLog.d(TAG, "performFiltering valueText " + valueText + "  " + (valueText.startsWith(prefixString)));
					// First match against the whole, non-splitted value
					if (valueText.startsWith(prefixString)) {
						newValues.add(value);
					} else {
//						final String[] words = valueText.split(" ");
//						final int wordCount = words.length;
//						if(DEBUG)	MyLog.d(TAG, "performFiltering wordCount " + wordCount );
//						// Start at index 0, in case valueText starts with
//						// space(s)
//						for (int k = 0; k < wordCount; k++) {
//							if (words[k].startsWith(prefixString)) {
//								if(DEBUG) MyLog.d(TAG, "performFiltering words[k] " + words[k] + (words[k].startsWith(prefixString)) );
//								newValues.add(value);
//								break;
//							}
//						}

						if(valueText.contains(prefix)|| valueText.toLowerCase(Locale.getDefault()).contains(prefixString)){
							newValues.add(value);
						}
					}
				}

				results.values = newValues;
				results.count = newValues.size();
			}

			return results;
		}

		@Override
		protected void publishResults(CharSequence constraint, FilterResults results) {
			// noinspection unchecked
			if(DEBUG)	MyLog.d(TAG, "publishResults constraint " + constraint  + " results " + results.count + "  " + results.values);
			mObjects = (List<T>) results.values;
			if (results.count > 0) {
				notifyDataSetChanged();
			} else {
				notifyDataSetInvalidated();
			}
		}
	}

}
